<?php

class CDataModel{
	
	public static function getInsertStmt($model, $table, $db, $fields=null){
		unset($stmt);
		
		//Indicador de campos en caso de null se agregan todos
		$with_fields = ($fields) ? true : false;
		
		$query_fields = '';
		$query_values = '';
		$query_params = array();
		
		//Genera cadena de insert
		$count = 0;
		foreach(get_object_vars($model) as $field_name => $item){
			if(get_class($item)=='CModelField'){
				//Verifica si exista el campo como parametro
				if($with_fields){
					if($fields[$field_name]) { $add_field = true; }
					else { $add_field = false; }
				}else { $add_field = true; }
				
				if(
				$item->db !=null & 
				$item->db[CDBTag::AutoGenerate] == false &
				$item->db[CDBTag::ReadOnly] == false &
				$add_field){
					if($count>0)
					{ $query_fields .= ", "; $query_values .= ", "; }
					$query_fields .= $item->db['field'];
					if($item->value==null & $item->db['isnull']==false){
						Debug::Write("Error 501. CDataModel:getInsertStmt:$table ; $field_name no soporta null.");
					}else{
						$param = ":".$item->db['field'];
						$query_values .= $param;
						$query_params[$param] = strtoupper($item->value);
					}
					$count++;
				}
			}
		}
		
		//Prepara stmt
		$stmt = $db->prepare(
			"SET DATEFORMAT DMY INSERT INTO $table ($query_fields) VALUES ($query_values)");
 
		//echo "SET DATEFORMAT DMY INSERT INTO $table ($query_fields) VALUES ($query_values)";
		
		//Asigna valores a los parametros
		foreach($query_params as $param => $value)
		{ 
			if($value==null)
			{ $stmt->bindValue($param, $value, PDO::PARAM_NULL); }
			else 
			{ $stmt->bindValue($param, $value); }
			//echo " PARAM($param)->$value <br/>"; 
		}
		
		return $stmt;
	}
	
	public static function getUpdateStmt($model, $table, $db, $where_conditions=null, $fields=null){
		unset($stmt);
		
		//Indicador de campos en caso de null se agregan todos
		$with_fields = ($fields) ? true : false;
		
		$query_fields = '';
		$query_params = array();
		
		//Genera cadena de insert
		$count = 0;
		foreach(get_object_vars($model) as $field_name => $item){
			if(get_class($item)=='CModelField'){
				//Verifica si exista el campo como parametro
				if($with_fields){
					if($fields[$field_name]) { $add_field = true; }
					else { $add_field = false; }
				}else { $add_field = true; }
				if(
				$item->db !=null & 
				$item->db[CDBTag::AutoGenerate] == false &
				$item->db[CDBTag::ReadOnly] == false & 
				$item->db[CDBTag::NoUpdate] == false &
				$add_field){
					if($count>0)
					{ $query_fields .= ", "; }
					if($item->value==null & $item->db['isnull']==false){
						Debug::Write("Error 501. CDataModel:getUpdateStmt:$table ; $field_name no soporta null.");
					}else{
						$param = $item->db['field'];
						$query_fields .= " $param = :$param ";
						$query_params[':'.$param] = $item->value;
					}
					$count++;
				}
			}
		}

		if($where_conditions==null){
			//Generar condicion en base a modelo usa el primarykey
			$primary = self::getPrimaryKeyField($model);
			if($primary){
				$query_params[':'.$primary->db['field']] = $primary->value;
				$where_conditions = array(
				new CWhereCondition($primary->db['field'], CWhereCondition::EQUALS));
			}else{
				Log::Write("Error 501. getSelectStmt:$table ; ".get_class($model)." no contine un campo primarykey yno hay clausulas where.");
				$where_conditions=array();
			}
		}else{
			foreach($where_conditions as $item){
				if(
				$item->_operator != CWhereCondition::NOT_NULL &&
				$item->_operator != CWhereCondition::IN_LIST
				){
					//echo $item->_name_field." :: ".$item->_values[0];
					$query_params[':'.$item->_name_field] = $item->_values[0];
				}
			}
		}
		
		$where = self::getWhereQuery($where_conditions);
		if($where!=null){ $where = "$where"; }else{ $where = ""; }
		
		$stmt = $db->prepare("SET DATEFORMAT DMY UPDATE $table SET $query_fields WHERE $where");
		
		//echo "SET DATEFORMAT DMY UPDATE $table SET $query_fields WHERE $where"; //die();
		//Asigna valores a los parametros
		foreach($query_params as $param => $value)
		{
			//echo "<br/> :: $param -> $value :: "; 
			if($value==null)
			{ $stmt->bindValue($param, $value, PDO::PARAM_NULL); }
			else 
			{ $stmt->bindValue($param, $value, PDO::PARAM_STR); } 
		}
		return $stmt;
	}

	public static function getSelectStmt($model, $table, $db, $where_conditions=null, $order_by=null){
		unset($stmt);
		$order_by = ($order_by!=null) ? "ORDER BY $order_by": "";
		
		$query_fields = '';
		$query_params = array();
		
		//Genera cadena de insert
		$count = 0;
		foreach(get_object_vars($model) as $field_name => $item){
			if(get_class($item)=='CModelField'){
				//Verifica si exista el campo como parametro
				if($with_fields){
					if($fields[$field_name]) 
					{ $add_field = true; }
					else { $add_field = false; }
				}else { $add_field = true; }
				if($item->db !=null & $add_field){
					if($count>0)
					{ $query_fields .= ", "; }
					$query_fields .= $item->db['field'];
					$count++;
				}
			}
		}
		
		if($where_conditions==null){
			//Generar condicion en base a modelo usa el primarykey
			$primary = self::getPrimaryKeyField($model);
			if($primary){
				$query_params[':'.$primary->db['field']] = $primary->value;
				$where_conditions = array(
				new CWhereCondition($primary->db['field'], CWhereCondition::EQUALS));
			}else{
				Log::Write("Error 501. getSelectStmt:$table ; ".get_class($model)." no contine un campo primarykey yno hay clausulas where.");
				$where_conditions=array();
			}
		}else{
			foreach($where_conditions as $item){
				if(
				$item->_operator != CWhereCondition::NOT_NULL &&
				$item->_operator != CWhereCondition::IN_LIST &&  
				$item->_operator != CWhereCondition::ISNULL 
				){
					$query_params[':'.$item->_name_field] = $item->_values[0];
				}
			}
		}
		
		$where = self::getWhereQuery($where_conditions);
		if($where!=null){ $where = "WHERE $where"; }else{ $where = ""; }
		
		$stmt = $db->prepare("SELECT $query_fields FROM $table $where $order_by");
		//echo "SELECT $query_fields FROM $table $where $order_by";

		//Asigna valores a los parametros
		foreach($query_params as $param => $value)
		{ 
			$stmt->bindValue($param, $value); 
			//echo " PARAM($param)->$value <br/>"; 
		}
		
		return $stmt;
	}
	
	/** 
	 * 	Obtiene un objeto CModelField con el primary key del modelo, en caso
	 *	de no existir retorna null
	 * @param CBaseModel $model
	 */
	protected static function getPrimaryKeyField($model){
		foreach(get_object_vars($model) as $field_name => $item){
			if(get_class($item)=='CModelField'){
				if($item->db['primarykey']==true)
				{ return $item; }
			}
		}
		return null;
	}

	protected static function getWhereQuery($where_conditions){
		$query = null;
		$count = 0;
		foreach($where_conditions as $item){
			if($count>0){ $query .= ' AND '; }
			if($item->_operator != CWhereCondition::IN_LIST){
				$query .= self::getConditional($item);
			}else{
				$ids = '';
				$quote = false;
				foreach($item->_values as $value){
					if($quote){ $ids .= ', '; }
					$ids .= $value;
					$quote = true;
				}
				$query .= $item->_name_field." IN ($ids)";
			}
			$count++;
		}
	
		return $query;
	}
	
	protected static function getConditional($condition){
		switch($condition->_operator){
			case CWhereCondition::EQUALS:
				return $condition->_name_field.' = :'.$condition->_name_field;
				break;
			case CWhereCondition::MORE_THAN:
				return $condition->_name_field.' > :'.$condition->_name_field;
				break;
			case CWhereCondition::MORE_EQUALS_THAN:
				return $condition->_name_field.' >= :'.$condition->_name_field;
				break;
			case CWhereCondition::LESS_THAN:
				return $condition->_name_field.' < :'.$condition->_name_field;
				break;
			case CWhereCondition::LESS_EQUALS_THAN:
				return $condition->_name_field.' <= :'.$condition->_name_field;
				break;
			case CWhereCondition::NOT_NULL:
				return $condition->_name_field.' IS NOT NULL';
				break;
			case CWhereCondition::ISNULL:
				return $condition->_name_field.' IS NULL';
				break;
		}
	}
}
